	title "profile interrupt handler for the Corollary MP machines"
;++
;
;Copyright (c) 1992, 1993, 1994  Corollary Inc
;
;Module Name:
;
;    cbusprof.asm
;
;Abstract:
;
;   This module contains the profile interrupt handler for the
;   non-boot processors in the Corollary MP machines.  This is
;   only needed because only one processor should ack the CMOS
;   for each profile interrupt.
;
;Author:
;
;   Landy Wang (landy@corollary.com) 26-Mar-1992
;
;Revision History:
;
;--



.386p
        .xlist
include halx86.inc
include callconv.inc                    ; calling convention macros
include x86\kimacro.inc
include cbus.inc

        EXTRNP  _HalBeginSystemInterrupt,3
        EXTRNP  _HalEndSystemInterrupt,2
ifdef CBC_REV1
        EXTRNP  _Cbus2RequestSoftwareInterrupt,1
endif

        .list


_TEXT	SEGMENT DWORD PUBLIC 'CODE'	; Start 32 bit code
        ASSUME  DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING


        page ,132
        subttl  "System Profile Interrupt for Additional Processors"
;++
;
; Routine Description:
;
;    This routine is entered as the result of a profile interrupt.
;    This routine is only entered by the non-boot processors.
;
;    The CMOS will be acked by the boot processor (only one CPU can
;    do this - which one is arbitrary, but it must only be ONE!).
;
;    This function thus, just raises system Irql to PROFILE_LEVEL
;    and transfers control to the standard system routine to process
;    any active profiles.
;
; Arguments:
;
;    None
;    Interrupt is disabled
;
; Return Value:
;
;    Does not return, jumps directly to KeProfileInterrupt, which returns
;
;    Sets Irql = PROFILE_LEVEL
;
;--
        ENTER_DR_ASSIST Hpx_a, Hpx_t

cPublicProc _HalpProfileInterruptPx     ,0

	;
	; Save machine state in trap frame
	;

        ENTER_INTERRUPT Hpx_a, Hpx_t

	;
	; (esp) - base of trap frame
	;

        push    _ProfileVector
        sub     esp, 4                  ; allocate space to save OldIrql
        stdCall   _HalBeginSystemInterrupt, <PROFILE_LEVEL,_ProfileVector,esp>

        ;
        ; if this is C-bus II, modify the vector so the interrupt
        ; will not be EOI'd.
        ;
        cmp     _Cbus2BridgesFound, 0
        je      short cbus1
        mov     eax, [_CbusClockVector]
        mov     [esp+4], eax
cbus1:

	;
	; The boot processor has already cleared (or is about to clear)
	; the interrupt flag on the RTC, so we don't do that here.
	;

        jmp     _HalpProfileInterrupt2ndEntry@0

stdENDP _HalpProfileInterruptPx


        page ,132
        subttl  "System Clock Interrupt for Additional Processors"
;++
;
; Routine Description:
;
;    This routine is entered as the result of an interrupt generated by CLOCK.
;    This routine is entered only by additional (non-boot) processors, so it
;    must NOT update the performance counter or update the system time.
;
;    instead, it just dismisses the interrupt, raises system Irql to
;    CLOCK2_LEVEL and transfers control to the standard system routine
;    to update the execution time of the current thread and process.
;
; Arguments:
;
;    None
;    Interrupt is disabled
;
; Return Value:
;
;    Does not return, jumps directly to KeUpdateRunTime, which returns
;
;    Sets Irql = CLOCK2_LEVEL and dismisses the interrupt
;
;--
        ENTER_DR_ASSIST Hcix_a, Hcix_t

cPublicProc _CbusClockInterruptPx   ,0

	;
	; Save machine state in trap frame
	; (esp) - base of trap frame
	;

        ENTER_INTERRUPT Hcix_a, Hcix_t

ifdef CBC_REV1
	;
	; because we can miss an interrupt due to a hardware bug in the
	; CBC rev 1 silicon, send ourselves an IPI on every clock.
	; since we don't know when we've missed one, this will ensure
	; we don't cause lock timeouts if nothing else!
	;

        stdCall _Cbus2RequestSoftwareInterrupt, <IPI_LEVEL>
endif

	;
	; Dismiss interrupt and raise irq level to clock2 level
	;

        push    _CbusClockVector
        sub     esp, 4                  ; allocate space to save OldIrql
        stdCall   _HalBeginSystemInterrupt, <CLOCK2_LEVEL, _CbusClockVector, esp>

	; Spurious interrupts on Corollary hardware are
	; directed to a different interrupt gate, so no need
	; to check return value above.

        POKE_LEDS eax, edx

        mov     eax, dword ptr [_CbusTimeStamp]
        mov     dword ptr [eax], 0

	;
	; (esp)   = OldIrql
	; (esp+4) = Vector
	; (esp+8) = base of trap frame
	;
	; (ebp)	  = base of trap frame for KeUpdateRunTime, this was set
	;		up by the ENTER_INTERRUPT macro above

        stdCall _KeUpdateRunTime,<dword ptr [esp]>

	INTERRUPT_EXIT

stdENDP _CbusClockInterruptPx

_TEXT	ends					; end 32 bit code
	end
